package com.yuyou.fn.analyze.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.github.wens.mybatisplus.plugins.Page;
import com.google.common.base.Predicate;
import com.google.common.collect.Collections2;
import com.yuyou.fn.analyze.service.IBusinessStatisticsService;
import com.yuyou.fn.analyze.service.IDataStatisticsService;
import com.yuyou.fn.analyze.service.IProductStatisticsService;
import com.yuyou.fn.analyze.vo.*;
import com.yuyou.fn.common.exception.BusException;
import com.yuyou.fn.common.service.ISiteConfigService;
import com.yuyou.fn.common.util.*;
import com.yuyou.fn.educational.entity.*;
import com.yuyou.fn.educational.service.*;
import com.yuyou.fn.educational.vo.CourseClassQueryVo;
import com.yuyou.fn.platform.entity.SysUser;
import com.yuyou.fn.platform.permission.DataPermission;
import com.yuyou.fn.platform.service.ISysDataPermissionService;
import com.yuyou.fn.report.entity.CostOfProduct;
import com.yuyou.fn.report.entity.RealIncomeOfClass;
import com.yuyou.fn.report.service.ICostOfProductService;
import com.yuyou.fn.report.service.IRealIncomeOfClassService;
import com.yuyou.fn.report.vo.*;
import com.yuyou.fn.settlement.entity.ChangeRecord;
import com.yuyou.fn.settlement.service.IChangeRecordService;
import com.yuyou.fn.settlement.vo.FeeCategoryTreeMapVo;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;

import static com.yuyou.fn.settlement.constant.FeeCategoryEnum.LEAVE;
import static com.yuyou.fn.settlement.constant.FeeCategoryEnum.SALARY_OF_COURSE;

/**
 * ProductTarget 表数据服务层接口实现类
 */
@Service
public class ProductStatistsServiceImpl implements IProductStatisticsService {
    @Resource
    private IProductService productService;

    @Resource
    private ICourseClassService courseClassService;

    @Resource
    private ISiteConfigService siteConfigService;

    @Resource
    private IClassLectureService classLectureService;

    @Resource
    private IChangeRecordService changeRecordService;

    @Resource
    private IBusinessStatisticsService businessStatisticsService;

    @Resource
    private IRoomPriceService roomPriceService;

    @Resource
    private ISysDataPermissionService sysDataPermissionService;

    @Resource
    private IDataStatisticsService dataStatisticsService;

    @Resource
    private ICostOfProductService costOfProductService;

    @Resource
    private IRealIncomeOfClassService realIncomeOfClassService;

    @Resource
    private IStudentRegService studentRegService;

    @Override
    public List<ProductCostAndIncomeVo> findProductCostAndIncome(Date startDate, Date endDate, List<Product> productList) {
        if (startDate.getTime()>endDate.getTime()){
            throw new BusException("开始时间必须小于等于结束时间");
        }
        List<ProductCostAndIncomeVo> productCostAndIncomeVoList=new ArrayList<ProductCostAndIncomeVo>();
        if (productList==null || productList.size()<=0 ){
            return productCostAndIncomeVoList;
        }
        List<Long> productIds = BeanUtils.toList(productList,"productId");

        List<CourseClass> courseClassesOfProduct = courseClassService.findBaseCourseClassByProductIds(productIds,"classId" ,"busTeamId","productId","startCourseTime","endCourseTime");
        courseClassesOfProduct = filterCourseClassesByDate(startDate, endDate, courseClassesOfProduct);

        List<Long> busTeamIdsOfProduct = BeanUtils.toList(courseClassesOfProduct,"busTeamId");
        busTeamIdsOfProduct = Utils.unique(busTeamIdsOfProduct);
        busTeamIdsOfProduct = this.filterBusTeamByPermissions(busTeamIdsOfProduct);
        List<CourseClass> courseClassesOfBusTeam = courseClassService.findBaseCourseClassByBusTeamIds(busTeamIdsOfProduct,"classId" ,"busTeamId","productId","startCourseTime","endCourseTime");
        courseClassesOfBusTeam=filterCourseClassesByDate(startDate,endDate,courseClassesOfBusTeam);


        Map<Long,List<CourseClass>> busTeamId2CourseClass = BeanUtils.toGroup(courseClassesOfBusTeam, "busTeamId");
        Map<Long,List<CourseClass>> productId2CourseClass = BeanUtils.toGroup(courseClassesOfProduct, "productId");

        List<Long> classIdsOfProduct = BeanUtils.toList(courseClassesOfProduct,"classId");
        List<ClassLecture> classLecturesOfProduct = classLectureService.findByClassIdAndTime(classIdsOfProduct, startDate, endDate,1,"classId","classDate");
        Map<Long,List<ClassLecture>> classId2ClassLecture = BeanUtils.toGroup(classLecturesOfProduct,"classId");


        List<Long> classIdsOfBusTeam = BeanUtils.toList(courseClassesOfProduct,"classId");
        List<ClassLecture> classLecturesOfBusTeam = classLectureService.findByClassIdAndTime(classIdsOfBusTeam, startDate, endDate,1,"classId","classDate");
        Map<Long,List<ClassLecture>> busTeam2ClassLecture = BeanUtils.toGroup(classLecturesOfBusTeam,"classId");


        //产品对应的统计
        List<ProductBusTeamClassVo> productBusTeamClassVoList = toProductBusTeamClassVo(productList, productId2CourseClass, classId2ClassLecture);
        //业务组对应的统计
        List<BusTeamClassVo> busTeamClassVoList = toBusTeamClassVo(busTeamIdsOfProduct, busTeamId2CourseClass, busTeam2ClassLecture);

        Map<Long,BusTeamClassVo> busTeamClassVoMap=BeanUtils.toMap(busTeamClassVoList,"busTeamId");

        String mainAccountFeeCategory = siteConfigService.getConfigValueFromCache("product_feeCategory");
        List<FeeCategoryTreeMapVo> allFeeCategoryTreeMapVoList = JSONArray.parseArray(mainAccountFeeCategory, FeeCategoryTreeMapVo.class);
        List<Long> feeCategoryIdList=new ArrayList<Long>(allFeeCategoryTreeMapVoList.size() * 10 );
        businessStatisticsService.fillAllFeeCategoryId(feeCategoryIdList,allFeeCategoryTreeMapVoList);

        List<ClassIncomeVo> allClassIncomeList=businessStatisticsService.classIncomeDetail(busTeamIdsOfProduct,startDate,endDate);
        Map<Long,List<ClassIncomeVo>> allClassIncomeMap=BeanUtils.toGroup(allClassIncomeList,"mainAccountId");
        List<ChangeRecord> allCostList=changeRecordService.findByCategoryIdsAndMainAccountIds(busTeamIdsOfProduct,0,"cost",startDate,endDate,feeCategoryIdList);
        Map<Long,List<ChangeRecord>> allCostMap=BeanUtils.toGroup(allCostList,"mainAccountId");

        for (ProductBusTeamClassVo productBusTeamClassVo:productBusTeamClassVoList){
            ProductCostAndIncomeVo productCostAndIncomeVo=new ProductCostAndIncomeVo();
            productCostAndIncomeVo.setProductName(productBusTeamClassVo.getProductName());
            productCostAndIncomeVo.setProductId(productBusTeamClassVo.getProductId());
            BigDecimal cost=BigDecimal.ZERO;
            BigDecimal income=BigDecimal.ZERO;
            List<BusTeamClassVo> productBusTeamClassVos=productBusTeamClassVo.getBusTeamClassVoList();

            if (productBusTeamClassVos!=null){
                for (BusTeamClassVo busTeamClassVo:productBusTeamClassVos){
                    List<CourseClass> courseClassList=busTeamClassVo.getCourseClassList();
                    List<ClassIncomeVo> classIncomeVoList=allClassIncomeMap.get(busTeamClassVo.getBusTeamId());//businessStatisticsService.classIncomeDetail(Arrays.asList(busTeamClassVo.getBusTeamId()),COURSE_INCOME.id,startDate,endDate);
                    Map<Long,ClassIncomeVo> map=BeanUtils.toMap(classIncomeVoList,"classId");
                    for (CourseClass courseClass:courseClassList){
                        ClassIncomeVo classIncomeVo=map.get(courseClass.getClassId());
                        if (classIncomeVo!=null && courseClass.getProductId().equals(classIncomeVo.getProductId())){
                            income=income.add(map.get(courseClass.getClassId()).getTotalIncomeAmount());
                        }
                    }
                    List<ChangeRecord> costList=allCostMap.get(busTeamClassVo.getBusTeamId());//changeRecordService.findByCategoryIdsAndMainAccountIds(Arrays.asList(busTeamClassVo.getBusTeamId()),0,"cost",startDate,endDate,feeCategoryIdList);
                    List<CategoryMainAccountVo> categoryMainAccountVoList=businessStatisticsService.toMainAccountCostList(allFeeCategoryTreeMapVoList,costList,busTeamClassVo.getBusTeamId());
                    if (busTeamClassVoMap.containsKey(busTeamClassVo.getBusTeamId())){
                        BusTeamClassVo allBusTeamClassVo=busTeamClassVoMap.get(busTeamClassVo.getBusTeamId());
                        categoryMainAccountVoList = this.calProductCostAlgorithm(busTeamClassVo.getClassLectureList(),courseClassList,busTeamClassVo.getBusTeamId(),categoryMainAccountVoList,allBusTeamClassVo.getInTimeTotalLecture(),busTeamClassVo.getInTimeTotalLecture(),startDate,endDate);
                        for(CategoryMainAccountVo categoryMainAccountVo : categoryMainAccountVoList ){
                            cost = cost.add(categoryMainAccountVo.getTotalAmount());
                        }
                    }
                }
            }
            productCostAndIncomeVo.setCost(cost);
            productCostAndIncomeVo.setIncome(income);
            productCostAndIncomeVo.setProfits(income.subtract(cost));
            productCostAndIncomeVoList.add(productCostAndIncomeVo);
        }

        return productCostAndIncomeVoList;
    }

    @Override
    public List<ProductCostAndIncomeVo> findProductCostAndIncome(List<Long> areaTeamIds,Date startDate, Date endDate, List<Product> productList, SysUser sysUser) {
        if (startDate.getTime()>endDate.getTime()){
            throw new BusException("开始时间必须小于等于结束时间");
        }
        List<ProductCostAndIncomeVo> productCostAndIncomeVoList=new ArrayList<ProductCostAndIncomeVo>();
        if (productList==null || productList.size()<=0 ){
            return productCostAndIncomeVoList;
        }
        List<Long> productIds=BeanUtils.toList(productList,"productId");

        List<Long> busTeamIds=dataStatisticsService.findPermissionBusTeam(areaTeamIds,sysUser.getUserId());

        if ( busTeamIds.size()<=0){
            return productCostAndIncomeVoList;
        }

        RealIncomeClassQueryVo realIncomeClassQueryVo=new RealIncomeClassQueryVo();
        realIncomeClassQueryVo.setBusTeamIds(busTeamIds);
        realIncomeClassQueryVo.setProductIds(productIds);
        realIncomeClassQueryVo.setStartDate(startDate);
        realIncomeClassQueryVo.setEndDate(endDate);
        List<ProductIncomeVo> realIncomeOfClassList=realIncomeOfClassService.findProductIncome(realIncomeClassQueryVo);

        CostOfProductQueryVo costOfProductQueryVo=new CostOfProductQueryVo();
        costOfProductQueryVo.setMainAccountIds(busTeamIds);
        costOfProductQueryVo.setProductIds(productIds);
        costOfProductQueryVo.setStartDate(startDate);
        costOfProductQueryVo.setEndDate(endDate);
        List<ProductCostVo> costOfProductList=costOfProductService.findProductCost(costOfProductQueryVo);

        Map<Long,ProductCostVo> costOfProductMap=BeanUtils.toMap(costOfProductList,"productId");
        Map<Long,ProductIncomeVo> realIncomeOfClassMap=BeanUtils.toMap(realIncomeOfClassList,"productId");
        for (Product product:productList){
            ProductCostAndIncomeVo productCostAndIncomeVo=new ProductCostAndIncomeVo();
            BigDecimal cost=BigDecimal.ZERO;
            BigDecimal income=BigDecimal.ZERO;
            BigDecimal profits=BigDecimal.ZERO;
            ProductCostVo costOfOneProduct=costOfProductMap.get(product.getProductId());
            ProductIncomeVo realIncomeOfOneProduct=realIncomeOfClassMap.get(product.getProductId());
            if (costOfOneProduct!=null && costOfOneProduct.getAmount()!=null){
                cost=cost.add(costOfOneProduct.getAmount());
            }
            if (realIncomeOfOneProduct!=null && realIncomeOfOneProduct.getAmount()!=null){
                income=income.add(realIncomeOfOneProduct.getAmount());
            }
            profits=income.subtract(cost);
            productCostAndIncomeVo.setCost(cost);
            productCostAndIncomeVo.setIncome(income);
            productCostAndIncomeVo.setProductId(product.getProductId());
            productCostAndIncomeVo.setProfits(profits);
            productCostAndIncomeVo.setProductName(product.getName());
            productCostAndIncomeVoList.add(productCostAndIncomeVo);
        }
        return productCostAndIncomeVoList;
    }

    private List<CourseClass> filterCourseClassesByDate(Date startDate, Date endDate, List<CourseClass> courseClassesOfProduct) {
        DataPermission dataPermission = sysDataPermissionService.findDataPermissionForUser(Principals.get().id);
        if (courseClassesOfProduct==null ){
            return Collections.EMPTY_LIST;
        }
        List<CourseClass> courseClassesOfProduct2 = new ArrayList<>(courseClassesOfProduct.size());
        for(CourseClass courseClass : courseClassesOfProduct){
            if(!dataPermission.getBusTeamIds().contains(courseClass.getBusTeamId()) || (courseClass.getEndCourseTime()!=null && courseClass.getEndCourseTime().getTime()<startDate.getTime()) || (courseClass.getStartCourseTime()!=null && courseClass.getStartCourseTime().getTime()>endDate.getTime()) ){
                continue;
            }
            courseClassesOfProduct2.add(courseClass);
        }
        return courseClassesOfProduct2;
    }

    private List<ProductBusTeamClassVo> toProductBusTeamClassVo(List<Product> productList, Map<Long, List<CourseClass>> productId2CourseClass, Map<Long, List<ClassLecture>> classId2ClassLecture) {
        List<ProductBusTeamClassVo> productBusTeamClassVoList = new ArrayList<>(productList.size());
        for (Product product : productList) {
            ProductBusTeamClassVo productBusTeamClassVo = new ProductBusTeamClassVo();
            productBusTeamClassVo.setProductId(product.getProductId());
            productBusTeamClassVo.setProductName(product.getName());
            if(productId2CourseClass != null ){
                List<CourseClass> courseClassList = productId2CourseClass.get(product.getProductId());
                Map<Long,List<CourseClass>> busTeamIds2CourseClass = BeanUtils.toGroup(courseClassList,"busTeamId");
                List<Long> busTeamIds = BeanUtils.toList(courseClassList,"busTeamId");
                busTeamIds = Utils.unique(busTeamIds);
                busTeamIds = filterBusTeamByPermissions(busTeamIds);
                productBusTeamClassVo.setBusTeamClassVoList(toBusTeamClassVo(busTeamIds,busTeamIds2CourseClass,classId2ClassLecture));
            }

            productBusTeamClassVoList.add(productBusTeamClassVo);
        }
        return productBusTeamClassVoList;
    }

    private List<BusTeamClassVo> toBusTeamClassVo(List<Long> busTeamIds, Map<Long, List<CourseClass>> busTeamId2CourseClass, Map<Long, List<ClassLecture>> classId2ClassLecture) {
        List<BusTeamClassVo> busTeamClassVoList = new ArrayList<BusTeamClassVo>(busTeamIds.size());
        for (Long busTeamId : busTeamIds) {
            BusTeamClassVo busTeamClassVo = new BusTeamClassVo();
            busTeamClassVo.setBusTeamId(busTeamId);
            List<CourseClass> subCourseClassList = busTeamId2CourseClass.get(busTeamId);
            List<ClassLecture> classLectures=new ArrayList<ClassLecture>(subCourseClassList.size() * 10 );
            for (CourseClass courseClass : subCourseClassList) {
                if(classId2ClassLecture != null ){
                    List<ClassLecture> list = classId2ClassLecture.get(courseClass.getClassId());
                    if (list!=null){
                        classLectures.addAll(classId2ClassLecture.get(courseClass.getClassId()));
                    }
                }
            }
            if (!subCourseClassList.isEmpty()){
                busTeamClassVo.setClassLectureList(classLectures);
                busTeamClassVo.setCourseClassList(subCourseClassList);
                busTeamClassVo.setInTimeTotalLecture(classLectures.size());
                busTeamClassVoList.add(busTeamClassVo);
            }

        }
        return busTeamClassVoList;
    }

    @Override
    public List<ClassIncomeVo> findClassIncomeByProductId(final Long productId, Date startDate, Date endDate) {
        if (startDate.getTime()>endDate.getTime()){
            throw new BusException("开始时间必须小于等于结束时间");
        }
        List<CourseClass> courseClassesOfProduct = courseClassService.findBaseCourseClassByProductIds(Arrays.asList(productId),"classId" ,"busTeamId","productId","startCourseTime","endCourseTime");
        courseClassesOfProduct = filterCourseClassesByDate(startDate, endDate, courseClassesOfProduct);
        List<Long> busTeamIdsOfProduct = BeanUtils.toList(courseClassesOfProduct,"busTeamId");
        busTeamIdsOfProduct=this.filterBusTeamByPermissions(busTeamIdsOfProduct);
        busTeamIdsOfProduct = Utils.unique(busTeamIdsOfProduct);
        List<ClassIncomeVo> allClassIncomeList = businessStatisticsService.classIncomeDetail(busTeamIdsOfProduct,startDate,endDate);
        return new ArrayList<>( Collections2.filter(allClassIncomeList, new Predicate<ClassIncomeVo>() {
            @Override
            public boolean apply(ClassIncomeVo input) {
                return productId.equals(input.getProductId());
            }
        }));
    }


    @Override
    public List<ClassIncomeVo> findClassIncomeByProductId(Long productId, Date startDate, Date endDate, SysUser sysUser) {
        if (startDate.getTime()>endDate.getTime()){
            throw new BusException("开始时间必须小于等于结束时间");
        }
        List<ClassIncomeVo> classIncomeVoList=new ArrayList<>();
        Product product=productService.findById(productId);
        List<Long> busTeamIds=dataStatisticsService.findPermissionBusTeam(Arrays.asList(product.getAreaTeamId()),sysUser.getUserId());

        List<RealIncomeOfClass> realIncomeOfClassList=realIncomeOfClassService.findRealIncomeOfClassByBusTeamIdsProductIds(busTeamIds,Arrays.asList(productId),startDate,endDate);

        Map<Long,List<RealIncomeOfClass>> map=BeanUtils.toGroup(realIncomeOfClassList,"classId");
        List<Long> classIdList=BeanUtils.toList(realIncomeOfClassList,"classId");

        classIdList=Utils.removeDuplicate(classIdList);

        List<CourseClass> courseClassList=courseClassService.findByIds(classIdList,"classId","className","busTeamId","busTeamName","areaTeamId","areaTeamName","gradeId","gradeName","subjectId","subjectName","lectureAmount","studyingFee","regAmount","productId","periodId");

        List<StudentReg> studentRegList=studentRegService.findListByClassIds(classIdList,0,"classId","payAmount","refundAmount");
        Map<Long,List<StudentReg>> regMap=BeanUtils.toGroup(studentRegList,"classId");
        for (CourseClass courseClass:courseClassList){
            ClassIncomeVo classIncomeVo=new ClassIncomeVo();
            classIncomeVo.setClassId(courseClass.getClassId());
            classIncomeVo.setGradeId(courseClass.getGradeId());
            classIncomeVo.setGradeName(courseClass.getGradeName());
            classIncomeVo.setSubjectId(courseClass.getSubjectId());
            classIncomeVo.setSubjectName(courseClass.getSubjectName());
            classIncomeVo.setClassName(courseClass.getClassName());
            classIncomeVo.setLectureAmount(courseClass.getLectureAmount());
            classIncomeVo.setStudyingFee(courseClass.getStudyingFee());
            classIncomeVo.setPeriodId(courseClass.getPeriodId());
            classIncomeVo.setRegAmount(courseClass.getRegAmount());
            classIncomeVo.setAreaTeamId(courseClass.getAreaTeamId());
            classIncomeVo.setAreaTeamName(courseClass.getAreaTeamName());
            classIncomeVo.setBusTeamId(courseClass.getBusTeamId());
            classIncomeVo.setBusTeamName(courseClass.getBusTeamName());
            classIncomeVo.setProductId(courseClass.getProductId());
            classIncomeVo.setMainAccountId(courseClass.getBusTeamId());
            classIncomeVo.setCompletedLectureAmount(courseClass.getCompletedLectureAmount());

            BigDecimal advanceAmount=BigDecimal.ZERO;
            List<StudentReg> oneStudentRegList=regMap.get(courseClass.getClassId());
            if (oneStudentRegList!=null){
                for (StudentReg studentReg:oneStudentRegList){
                    advanceAmount=advanceAmount.add(studentReg.getPayAmount().subtract(studentReg.getRefundAmount()));
                }
            }
            classIncomeVo.setAdvanceAmount(advanceAmount);
            List<RealIncomeOfClass> realIncomeOfOneClassList=map.get(courseClass.getClassId());
            if (realIncomeOfOneClassList!=null){
                Set<Long> lectureSet=new HashSet<>();
                BigDecimal totalAmount=BigDecimal.ZERO;
                for (RealIncomeOfClass realIncomeOfClass:realIncomeOfOneClassList){
                    lectureSet.add(realIncomeOfClass.getLectureId());
                    totalAmount=totalAmount.add(realIncomeOfClass.getAmount());
                }
                classIncomeVo.setHappenLectureAmount(lectureSet.size());
                classIncomeVo.setTotalIncomeAmount(totalAmount);
            }
            classIncomeVoList.add(classIncomeVo);

        }
        return classIncomeVoList;

    }

    @Override
    public Page<ClassIncomeVo> findClassIncomePageByProductId(Long productId, Date startDate, Date endDate,SysUser sysUser, int pageNo,int pageSize) {
        Product product=productService.findById(productId);
        List<Long> busTeamIds=dataStatisticsService.findPermissionBusTeam(Arrays.asList(product.getAreaTeamId()),sysUser.getUserId());
        CourseClassQueryVo courseClassQueryVo=new CourseClassQueryVo();
        courseClassQueryVo.setProductId(productId);
        courseClassQueryVo.setBusTeamIds(busTeamIds);
        Page<CourseClass> courseClassPage=courseClassService.findCourseClassByQuery(courseClassQueryVo,pageNo,pageSize);
        Page<ClassIncomeVo> classIncomeVoPage= Utils.newPage(courseClassPage);
        List<CourseClass> courseClassList=courseClassPage.getRecords();
        if (courseClassList!=null && courseClassList.size()>0){
            List<ClassIncomeVo> classIncomeVoList=new ArrayList<>(courseClassList.size());
            List<Long> classIds=BeanUtils.toList(courseClassList,"classId");
            List<StudentReg> studentRegList=studentRegService.findListByClassIds(classIds,0,"classId","payAmount","refundAmount");
            Map<Long,List<StudentReg>> regMap=BeanUtils.toGroup(studentRegList,"classId");
            RealIncomeClassQueryVo realIncomeClassQueryVo=new RealIncomeClassQueryVo();
            realIncomeClassQueryVo.setStartDate(startDate);
            realIncomeClassQueryVo.setEndDate(endDate);
            realIncomeClassQueryVo.setClassIds(classIds);
            List<ClassAmountVo> classAmountVoList=realIncomeOfClassService.findClassAmount(realIncomeClassQueryVo);
            Map<Long,ClassAmountVo> map=BeanUtils.toMap(classAmountVoList,"classId");
            for (CourseClass courseClass:courseClassList){
                ClassIncomeVo classIncomeVo=new ClassIncomeVo();
                BeanUtils.copyProperties(classIncomeVo,courseClass);
                classIncomeVo.setMainAccountId(courseClass.getBusTeamId());
                ClassAmountVo classAmountVo=map.get(courseClass.getClassId());
                if (classAmountVo!=null){
                    classIncomeVo.setHappenLectureAmount(classAmountVo.getHappenLectureAmount());
                    classIncomeVo.setTotalIncomeAmount(classAmountVo.getAmount());
                }
                BigDecimal advanceAmount=BigDecimal.ZERO;
                List<StudentReg> oneStudentRegList=regMap.get(courseClass.getClassId());
                if (oneStudentRegList!=null){
                    for (StudentReg studentReg:oneStudentRegList){
                        advanceAmount=advanceAmount.add(studentReg.getPayAmount().subtract(studentReg.getRefundAmount()));
                    }
                }
                classIncomeVo.setAdvanceAmount(advanceAmount);

                classIncomeVoList.add(classIncomeVo);
            }
            classIncomeVoPage.setRecords(classIncomeVoList);
        }
        return classIncomeVoPage;
    }

    @Override
    public List<Long> filterBusTeamByPermissions(List<Long> busTeamIdList) {
        DataPermission dataPermission = sysDataPermissionService.findDataPermissionForUser(Principals.get().id);
        List<Long> permissionBusTeamIdList= dataPermission.getBusTeamIds() ;
        busTeamIdList.retainAll(permissionBusTeamIdList);
        return busTeamIdList;
    }



    @Override
    public List<BusTeamClassVo> findBusTeamsClassLeature(List<Long> busTeamIdList, List<CourseClass> courseClassList,List<ClassLecture> classLectureList, Date startDate, Date endDate) {
        if (busTeamIdList == null || busTeamIdList.size() <= 0 || courseClassList == null || courseClassList.size() <= 0) {
            return Collections.EMPTY_LIST;
        }
        List<BusTeamClassVo> busTeamClassVoList = new ArrayList<BusTeamClassVo>();
        Map<Long, List<ClassLecture>> map = BeanUtils.toGroup(classLectureList, "classId");
        for (Long busTeamId : busTeamIdList) {
            BusTeamClassVo busTeamClassVo = new BusTeamClassVo();
            busTeamClassVo.setBusTeamId(busTeamId);
            Integer inTimeTotalLecture = 0;
            List<CourseClass> subCourseClassList = new ArrayList<CourseClass>();
            List<ClassLecture> classLectures=new ArrayList<ClassLecture>();
            for (CourseClass courseClass : courseClassList) {
                if (busTeamId.equals(courseClass.getBusTeamId())) {
                    subCourseClassList.add(courseClass);
                    inTimeTotalLecture = inTimeTotalLecture + (map.get(courseClass.getClassId()) == null ? 0 : map.get(courseClass.getClassId()).size());
                    List<ClassLecture> list=map.get(courseClass.getClassId());
                    if (list!=null){
                        classLectures.addAll(map.get(courseClass.getClassId()));
                    }
                }
            }
            if (inTimeTotalLecture>0){
                busTeamClassVo.setClassLectureList(classLectures);
                busTeamClassVo.setCourseClassList(subCourseClassList);
                busTeamClassVo.setInTimeTotalLecture(inTimeTotalLecture);
                busTeamClassVoList.add(busTeamClassVo);
            }

        }
        return busTeamClassVoList;
    }


    @Override
    public List<CategoryMainAccountVo> calProductCostAlgorithm(List<ClassLecture> classLectureListOfBusTeam, List<CourseClass> tempCourseClassList, Long mainAccountId, List<CategoryMainAccountVo> categoryMainAccountVoList, Integer busTeamTotalLectureAmount, Integer productLectureAmount, Date startDate, Date endDate ){
        List<CategoryMainAccountVo> newList = new ArrayList<>(categoryMainAccountVoList.size());
        for (CategoryMainAccountVo categoryMainAccountVo:categoryMainAccountVoList){
            CategoryMainAccountVo nVo = new CategoryMainAccountVo();
            BeanUtils.copyProperties(nVo,categoryMainAccountVo);
            if (categoryMainAccountVo.getCategoryId().equals(LEAVE.id)){//租金
                nVo.setTotalAmount( this.calLeaveOfClassLecture(classLectureListOfBusTeam) );
            }else if(categoryMainAccountVo.getCategoryId().equals(SALARY_OF_COURSE.id)){//任课课酬
                List<TeacherClassCostVo> teacherClassCostVoList=businessStatisticsService.classRemunerationDetail(mainAccountId,SALARY_OF_COURSE.id,startDate,endDate);
                Map<Long,List<TeacherClassCostVo>> map=BeanUtils.toGroup(teacherClassCostVoList,"classId");
                BigDecimal count  = BigDecimal.ZERO;
                for (CourseClass courseClass: tempCourseClassList){
                    if (map.containsKey(courseClass.getClassId())){
                        List<TeacherClassCostVo> teacherClassCostVos=map.get(courseClass.getClassId());
                        for (TeacherClassCostVo teacherClassCostVo:teacherClassCostVos){
                            count=count.add((teacherClassCostVo.getTotalClassRemuneration()));
                        }
                    }
                }
                nVo.setTotalAmount(count);
            }else if (categoryMainAccountVo.getChildren() == null){
                if (productLectureAmount==0 || busTeamTotalLectureAmount==0){
                    nVo.setTotalAmount(BigDecimal.ZERO);
                }else {
                    nVo.setTotalAmount(BigDecimals.calProportion(categoryMainAccountVo.getTotalAmount() , new BigDecimal(productLectureAmount) , new BigDecimal(busTeamTotalLectureAmount)));
                }
                //nVo.setTotalAmount(Utils.calProportion(categoryMainAccountVo.getTotalAmount() , new BigDecimal(productLectureAmount) , new BigDecimal(busTeamTotalLectureAmount)));
            }else if (categoryMainAccountVo.getChildren()!=null){
                nVo.setChildren(calProductCostAlgorithm( classLectureListOfBusTeam , tempCourseClassList,mainAccountId,categoryMainAccountVo.getChildren(),busTeamTotalLectureAmount ,productLectureAmount,startDate,endDate));
                BigDecimal count  = BigDecimal.ZERO;
                for(CategoryMainAccountVo cVo : nVo.getChildren() ){
                    count=count.add((cVo.getTotalAmount()));
                }
                nVo.setTotalAmount(count);
            }

            newList.add(nVo);
        }
        return newList;
    }

    @Override
    public List<ProductCostByCategoryVo> findProductCategoryCostByProductId(List<FeeCategoryTreeMapVo> feeCategoryTreeMapVoList, Long productId, Date startDate, Date endDate) {
        if (startDate.getTime()>endDate.getTime()){
            throw new BusException("开始时间必须小于等于结束时间");
        }
        Product product=productService.findById(productId);
        List<CourseClass> courseClassesOfProduct = courseClassService.findBaseCourseClassByProductIds(Arrays.asList(productId),"classId" ,"className","busTeamId","productId","startCourseTime","endCourseTime");
        courseClassesOfProduct = filterCourseClassesByDate(startDate, endDate, courseClassesOfProduct);
        List<Long> busTeamIdsOfProduct = BeanUtils.toList(courseClassesOfProduct,"busTeamId");
        busTeamIdsOfProduct = Utils.unique(busTeamIdsOfProduct);
        busTeamIdsOfProduct=this.filterBusTeamByPermissions(busTeamIdsOfProduct);
        List<CourseClass> courseClassesOfBusTeam = courseClassService.findBaseCourseClassByBusTeamIds(busTeamIdsOfProduct,"classId" ,"className","busTeamId","productId","startCourseTime","endCourseTime");
        Map<Long,List<CourseClass>> busTeamId2CourseClass = BeanUtils.toGroup(courseClassesOfBusTeam, "busTeamId");
        Map<Long,List<CourseClass>> productId2CourseClass = BeanUtils.toGroup(courseClassesOfProduct, "productId");

        List<Long> classIdsOfProduct = BeanUtils.toList(courseClassesOfProduct,"classId");
        List<ClassLecture> classLecturesOfProduct = classLectureService.findByClassIdAndTime(classIdsOfProduct, startDate, endDate,1,"classId","classDate");
        Map<Long,List<ClassLecture>> classId2ClassLecture = BeanUtils.toGroup(classLecturesOfProduct,"classId");

        List<Long> classIdsOfBusTeam = BeanUtils.toList(courseClassesOfBusTeam,"classId");
        List<ClassLecture> classLecturesOfBusTeam = classLectureService.findByClassIdAndTime(classIdsOfBusTeam, startDate, endDate,1,"classId","classDate");
        Map<Long,List<ClassLecture>> busTeam2ClassLecture = BeanUtils.toGroup(classLecturesOfBusTeam,"classId");


        //产品对应的统计
        List<ProductBusTeamClassVo> productBusTeamClassVoList = toProductBusTeamClassVo(Arrays.asList(product), productId2CourseClass, classId2ClassLecture);
        //业务组对应的统计
        List<BusTeamClassVo> busTeamClassVoList = toBusTeamClassVo(busTeamIdsOfProduct, busTeamId2CourseClass, busTeam2ClassLecture);

        Map<Long,BusTeamClassVo> busTeamClassVoMap=BeanUtils.toMap(busTeamClassVoList,"busTeamId");


        List<Long> feeCategoryIdList=new ArrayList<Long>(feeCategoryTreeMapVoList.size() * 10 );
        businessStatisticsService.fillAllFeeCategoryId(feeCategoryIdList,feeCategoryTreeMapVoList);

        List<ChangeRecord> allCostList=changeRecordService.findByCategoryIdsAndMainAccountIds(busTeamIdsOfProduct,0,"cost",startDate,endDate,feeCategoryIdList);
        Map<Long,List<ChangeRecord>> allCostMap=BeanUtils.toGroup(allCostList,"mainAccountId");

        if(productBusTeamClassVoList.size() != 1 ){
            return buildProductCostByCategoryVo( feeCategoryTreeMapVoList , Collections.EMPTY_LIST) ;
        }

        ProductBusTeamClassVo productBusTeamClassVo = productBusTeamClassVoList.get(0);
        ProductCostAndIncomeVo productCostAndIncomeVo=new ProductCostAndIncomeVo();
        productCostAndIncomeVo.setProductName(productBusTeamClassVo.getProductName());
        productCostAndIncomeVo.setProductId(productBusTeamClassVo.getProductId());
        List<BusTeamClassVo> productBusTeamClassVos=productBusTeamClassVo.getBusTeamClassVoList();


        if (productBusTeamClassVos == null){
            return buildProductCostByCategoryVo( feeCategoryTreeMapVoList , Collections.EMPTY_LIST) ;
        }

        List<CategoryMainAccountVo> productCategoryMainAccountVoList = new ArrayList<>(100 );
        for (BusTeamClassVo busTeamClassVo:productBusTeamClassVos){
            List<CourseClass> courseClassList=busTeamClassVo.getCourseClassList();
            List<ChangeRecord> costList=allCostMap.get(busTeamClassVo.getBusTeamId());//changeRecordService.findByCategoryIdsAndMainAccountIds(Arrays.asList(busTeamClassVo.getBusTeamId()),0,"cost",startDate,endDate,feeCategoryIdList);
            List<CategoryMainAccountVo> categoryMainAccountVoList=businessStatisticsService.toMainAccountCostList(feeCategoryTreeMapVoList,costList,busTeamClassVo.getBusTeamId());
            if (busTeamClassVoMap.containsKey(busTeamClassVo.getBusTeamId())){
                BusTeamClassVo allBusTeamClassVo=busTeamClassVoMap.get(busTeamClassVo.getBusTeamId());
                categoryMainAccountVoList = this.calProductCostAlgorithm(busTeamClassVo.getClassLectureList(),courseClassList,busTeamClassVo.getBusTeamId(),categoryMainAccountVoList,allBusTeamClassVo.getInTimeTotalLecture(),busTeamClassVo.getInTimeTotalLecture(),startDate,endDate);
                productCategoryMainAccountVoList.addAll(categoryMainAccountVoList);
            }
        }
        return buildProductCostByCategoryVo(feeCategoryTreeMapVoList, productCategoryMainAccountVoList);
    }


    @Override
    public List<ProductCostByCategoryVo> findProductCategoryCostByProductId(List<FeeCategoryTreeMapVo> feeCategoryTreeMapVoList, Long productId, Date startDate, Date endDate, SysUser sysUser) {
        if (startDate.getTime()>endDate.getTime()){
            throw new BusException("开始时间必须小于等于结束时间");
        }
        Product product=productService.findById(productId);
        List<Long> busTeamIds=dataStatisticsService.findPermissionBusTeam(Arrays.asList(product.getAreaTeamId()),sysUser.getUserId());

        List<Long> feeCategoryIdList=new ArrayList<Long>(feeCategoryTreeMapVoList.size() * 10 );
        businessStatisticsService.fillAllFeeCategoryId(feeCategoryIdList,feeCategoryTreeMapVoList);
        List<CostOfProduct> costOfProductList=costOfProductService.findCostByProductIdsAndFeeCategoryIds(Arrays.asList(productId),busTeamIds,startDate,endDate,feeCategoryIdList);
        return  buildCostOfProductByCategoryVo(feeCategoryTreeMapVoList,costOfProductList,product);
    }


    private List<ProductCostByCategoryVo> buildCostOfProductByCategoryVo(List<FeeCategoryTreeMapVo> allFeeCategoryTreeMapVoList, List<CostOfProduct> costOfProducts,Product product) {
        List<ProductCostByCategoryVo> productCostByCategoryVoList = new ArrayList<>(allFeeCategoryTreeMapVoList.size());
        Map<Long,List<CostOfProduct>> categoryId2CostOfProduct = BeanUtils.toGroup(costOfProducts,"feeCategoryId");
        for (FeeCategoryTreeMapVo feeCategoryTreeMapVo:allFeeCategoryTreeMapVoList){
            BigDecimal totalAmount=BigDecimal.ZERO;
            ProductCostByCategoryVo productCostByCategoryVo=new ProductCostByCategoryVo();
            productCostByCategoryVo.setCategoryId(feeCategoryTreeMapVo.getFeeCategoryId());
            productCostByCategoryVo.setName(feeCategoryTreeMapVo.getName());
            productCostByCategoryVo.setProductId(product.getProductId());
            if (categoryId2CostOfProduct.containsKey(feeCategoryTreeMapVo.getFeeCategoryId())){
                List<CostOfProduct> tempList=categoryId2CostOfProduct.get(feeCategoryTreeMapVo.getFeeCategoryId());
                for (CostOfProduct costOfProduct:tempList){
                    totalAmount=totalAmount.add(costOfProduct.getAmount());
                }
            }
            if (feeCategoryTreeMapVo.getChildren()!=null){
                totalAmount=this.countChirldAmount(feeCategoryTreeMapVo.getChildren(),categoryId2CostOfProduct);
            }

            productCostByCategoryVo.setTotalAmount(totalAmount);
            if (feeCategoryTreeMapVo.getFeeCategoryId().equals(SALARY_OF_COURSE.id)){
                productCostByCategoryVo.setDetailType(2);
            }else if (feeCategoryTreeMapVo.getChildren()==null){
                productCostByCategoryVo.setDetailType(0);
            }else if (feeCategoryTreeMapVo.getChildren()!=null){
                productCostByCategoryVo.setDetailType(1);
            }
            productCostByCategoryVoList.add(productCostByCategoryVo);
        }
        return productCostByCategoryVoList;
    }

    private BigDecimal countChirldAmount(List<FeeCategoryTreeMapVo> allFeeCategoryTreeMapVoList,Map<Long,List<CostOfProduct>> categoryId2CostOfProduct){
        BigDecimal totalAmount=BigDecimal.ZERO;
        for (FeeCategoryTreeMapVo feeCategoryTreeMapVo:allFeeCategoryTreeMapVoList){
            if (categoryId2CostOfProduct.containsKey(feeCategoryTreeMapVo.getFeeCategoryId())){
                List<CostOfProduct> tempList=categoryId2CostOfProduct.get(feeCategoryTreeMapVo.getFeeCategoryId());
                for (CostOfProduct costOfProduct:tempList){
                    totalAmount=totalAmount.add(costOfProduct.getAmount());
                }
            }
            if (feeCategoryTreeMapVo.getChildren()!=null){
                totalAmount=totalAmount.add(countChirldAmount(feeCategoryTreeMapVo.getChildren(),categoryId2CostOfProduct));
            }

        }
        return totalAmount;
    }




    @Override
    public List<ProductCostByCategoryVo> findProductCategoryCostByProductId(Long productId, Date startDate, Date endDate) {
        String mainAccountFeeCategory = siteConfigService.getConfigValueFromCache("product_feeCategory");
        List<FeeCategoryTreeMapVo> allFeeCategoryTreeMapVoList = JSONArray.parseArray(mainAccountFeeCategory, FeeCategoryTreeMapVo.class);
        return findProductCategoryCostByProductId(allFeeCategoryTreeMapVoList,productId,startDate,endDate );
    }



    private List<ProductCostByCategoryVo> buildProductCostByCategoryVo(List<FeeCategoryTreeMapVo> allFeeCategoryTreeMapVoList, List<CategoryMainAccountVo> productCategoryMainAccountVoList) {
        List<ProductCostByCategoryVo> productCostByCategoryVoList = new ArrayList<>(allFeeCategoryTreeMapVoList.size());
        Map<Long,List<CategoryMainAccountVo>> categoryId2CategoryMainAccountVo = BeanUtils.toGroup(productCategoryMainAccountVoList,"categoryId");
        for (FeeCategoryTreeMapVo feeCategoryTreeMapVo:allFeeCategoryTreeMapVoList){
            BigDecimal totalAmount=BigDecimal.ZERO;
            ProductCostByCategoryVo productCostByCategoryVo=new ProductCostByCategoryVo();
            productCostByCategoryVo.setCategoryId(feeCategoryTreeMapVo.getFeeCategoryId());
            productCostByCategoryVo.setName(feeCategoryTreeMapVo.getName());
            if (categoryId2CategoryMainAccountVo.containsKey(feeCategoryTreeMapVo.getFeeCategoryId())){
                List<CategoryMainAccountVo> tempList=categoryId2CategoryMainAccountVo.get(feeCategoryTreeMapVo.getFeeCategoryId());
                for (CategoryMainAccountVo categoryMainAccountVo:tempList){
                    totalAmount=totalAmount.add(categoryMainAccountVo.getTotalAmount());
                }
            }
            productCostByCategoryVo.setTotalAmount(totalAmount);
            if (feeCategoryTreeMapVo.getFeeCategoryId().equals(SALARY_OF_COURSE.id)){
                productCostByCategoryVo.setDetailType(2);
            }else if (feeCategoryTreeMapVo.getChildren()==null){
                productCostByCategoryVo.setDetailType(0);
            }else if (feeCategoryTreeMapVo.getChildren()!=null){
                productCostByCategoryVo.setDetailType(1);
            }
            productCostByCategoryVoList.add(productCostByCategoryVo);
        }
        return productCostByCategoryVoList;
    }

    @Override
    public List<Long> busTeamIdListByProductIds(List<Long> productIdList, Date startDate, Date endDate) {
        List<CourseClass> productCourseClassList=courseClassService.findSimpByProductIds(productIdList,"classId","busTeamId");
        Set<Long> set=new HashSet<Long>();
        for (CourseClass courseClass:productCourseClassList){
            set.add(courseClass.getBusTeamId());
        }
        List<Long> busTeamIdList=new ArrayList<Long>();
        busTeamIdList.addAll(set);
        return busTeamIdList;
    }

    @Override
    public List<TeacherClassCostVo> productClassRemunerationDetail(Long productId, Long feeCategoryId, Date startDate, Date endDate) {
        Product product = productService.findById(productId);
        List<TeacherClassCostVo> productTeacherClassCostVoList=new ArrayList<TeacherClassCostVo>();
        List<CourseClass> courseClassesOfProduct = courseClassService.findBaseCourseClassByProductIds(Arrays.asList(productId),"classId" ,"busTeamId","productId","startCourseTime","endCourseTime");
        courseClassesOfProduct = filterCourseClassesByDate(startDate, endDate, courseClassesOfProduct);
        Map<Long,List<CourseClass>> productId2CourseClass = BeanUtils.toGroup(courseClassesOfProduct, "productId");

        //产品对应的统计
        List<ProductBusTeamClassVo> productBusTeamClassVoList = toProductBusTeamClassVo(Arrays.asList(product), productId2CourseClass, null);

        for (ProductBusTeamClassVo productBusTeamClassVo:productBusTeamClassVoList){
            List<BusTeamClassVo> busTeamClassVoList=productBusTeamClassVo.getBusTeamClassVoList();
            for (BusTeamClassVo busTeamClassVo:busTeamClassVoList){
                List<TeacherClassCostVo> teacherClassCostVoList=businessStatisticsService.classRemunerationDetail(busTeamClassVo.getBusTeamId(),SALARY_OF_COURSE.id,startDate,endDate);
                Map<Long,List<TeacherClassCostVo>> map=BeanUtils.toGroup(teacherClassCostVoList,"classId");
                for (CourseClass courseClass:busTeamClassVo.getCourseClassList()){
                    if (map.containsKey(courseClass.getClassId())){
                        List<TeacherClassCostVo> teacherClassCostVos=map.get(courseClass.getClassId());
                        if (teacherClassCostVos!=null){
                            productTeacherClassCostVoList.addAll(teacherClassCostVos);
                        }
                    }
                }
            }
        }
        return productTeacherClassCostVoList;
    }

    @Override
    public List<TeacherClassCostVo> productClassRemunerationDetail(Long productId, Long feeCategoryId, Date startDate, Date endDate, SysUser sysUser) {

        Product product = productService.findById(productId);
        List<TeacherClassCostVo> productTeacherClassCostVoList=new ArrayList<TeacherClassCostVo>();
        List<Long> busTeamIds=dataStatisticsService.findPermissionBusTeam(Arrays.asList(product.getAreaTeamId()),sysUser.getUserId());

        List<CostOfProduct> costOfProductList=costOfProductService.findCostByProductIdsAndFeeCategoryIds(Arrays.asList(productId),busTeamIds,startDate,endDate,Arrays.asList(feeCategoryId));


        for (CostOfProduct costOfProduct:costOfProductList){
            TeacherClassCostVo teacherClassCostVo=new TeacherClassCostVo();
            teacherClassCostVo.setClassHour(2);
            teacherClassCostVo.setTotalClassRemuneration(costOfProduct.getAmount());
            teacherClassCostVo.setSettlementDate(costOfProduct.getCreateTime());
            teacherClassCostVo.setClassRemuneration(costOfProduct.getAmount().divide(new BigDecimal(2)));
            String extraString=costOfProduct.getExtra();
            Extra extra= JSONObject.parseObject(extraString,Extra.class);

            if (extra!=null ){
                teacherClassCostVo.setTeacherId(extra.getTeacherId());
                teacherClassCostVo.setTeacherName(extra.getTeacherName());
                teacherClassCostVo.setIdNo(extra.getIdNo());
                teacherClassCostVo.setPhoneNo(extra.getPhone());
                teacherClassCostVo.setClassId(extra.getClassId());
                teacherClassCostVo.setClassName(extra.getClassName());
                teacherClassCostVo.setAreaTeamName(extra.getAreaTeamName());
                teacherClassCostVo.setBusTeamName(extra.getBusTeamName());
                teacherClassCostVo.setLectureNo(extra.getLectureNo());
            }
            productTeacherClassCostVoList.add(teacherClassCostVo);
        }
        return productTeacherClassCostVoList;
    }

    @Override
    public Page<TeacherClassCostVo> productClassRemunerationPage(Long productId, Long feeCategoryId, Date startDate, Date endDate, SysUser sysUser,int pageNo,int pageSize) {
        Product product = productService.findById(productId);

        List<Long> busTeamIds=dataStatisticsService.findPermissionBusTeam(Arrays.asList(product.getAreaTeamId()),sysUser.getUserId());

        CostOfProductQueryVo costOfProductQueryVo=new CostOfProductQueryVo();
        costOfProductQueryVo.setEndDate(endDate);
        costOfProductQueryVo.setStartDate(startDate);
        costOfProductQueryVo.setProductId(productId);
        costOfProductQueryVo.setFeeCategoryId(feeCategoryId);
        costOfProductQueryVo.setMainAccountIds(busTeamIds);
        Page<CostOfProduct> costOfProductPage=costOfProductService.findProductCostPageByQueryVo(costOfProductQueryVo,pageNo,pageSize);

        Page<TeacherClassCostVo> teacherClassCostVoPage=Utils.newPage(costOfProductPage);
        List<CostOfProduct> costOfProductList=costOfProductPage.getRecords();
        if (costOfProductList!=null){
            List<TeacherClassCostVo> productTeacherClassCostVoList=new ArrayList<TeacherClassCostVo>(costOfProductList.size());
            for (CostOfProduct costOfProduct:costOfProductList){
                TeacherClassCostVo teacherClassCostVo=new TeacherClassCostVo();
                teacherClassCostVo.setClassHour(2);
                teacherClassCostVo.setTotalClassRemuneration(costOfProduct.getAmount());
                teacherClassCostVo.setSettlementDate(costOfProduct.getCreateTime());
                teacherClassCostVo.setClassRemuneration(costOfProduct.getAmount().divide(new BigDecimal(2)));
                String extraString=costOfProduct.getExtra();
                Extra extra= JSONObject.parseObject(extraString,Extra.class);
                if (extra!=null ){
                    teacherClassCostVo.setTeacherId(extra.getTeacherId());
                    teacherClassCostVo.setTeacherName(extra.getTeacherName());
                    teacherClassCostVo.setIdNo(extra.getIdNo());
                    teacherClassCostVo.setPhoneNo(extra.getPhone());
                    teacherClassCostVo.setClassId(extra.getClassId());
                    teacherClassCostVo.setClassName(extra.getClassName());
                    teacherClassCostVo.setAreaTeamName(extra.getAreaTeamName());
                    teacherClassCostVo.setBusTeamName(extra.getBusTeamName());
                    teacherClassCostVo.setLectureNo(extra.getLectureNo());
                }
                productTeacherClassCostVoList.add(teacherClassCostVo);
            }
            teacherClassCostVoPage.setRecords(productTeacherClassCostVoList);
        }
        return teacherClassCostVoPage;
    }

    @Override
    public ProductCostDetailVo findCostDetailByDetailType(Integer detailType, Long feeCategoryId, Long productId, Date startDate, Date endDate) {
        if (startDate.getTime()>endDate.getTime()){
            throw new BusException("开始时间必须小于等于结束时间");
        }
        ProductCostDetailVo productCostDetailVo=new ProductCostDetailVo();
        if (detailType==0){//明细

        }else if (detailType==1){//子类型
            String mainAccountFeeCategory = siteConfigService.getConfigValueFromCache("product_feeCategory");
            List<FeeCategoryTreeMapVo> allFeeCategoryTreeMapVoList = JSONArray.parseArray(mainAccountFeeCategory, FeeCategoryTreeMapVo.class);
            List<FeeCategoryTreeMapVo> feeCategoryTreeMapVoList=businessStatisticsService.findChildListByParentId(allFeeCategoryTreeMapVoList,feeCategoryId);
            List<ProductCostByCategoryVo> productCostByCategoryVoList=this.findProductCategoryCostByProductId(feeCategoryTreeMapVoList,productId,startDate,endDate);
            productCostDetailVo.setProductCostByCategoryVoList(productCostByCategoryVoList);
        }else if (detailType==2){//课酬
            List<TeacherClassCostVo> teacherClassCostVoList=this.productClassRemunerationDetail(productId,feeCategoryId,startDate,endDate);
            productCostDetailVo.setTeacherClassCostVoList(teacherClassCostVoList);
        }

        return productCostDetailVo;
    }


    @Override
    public ProductCostDetailVo findCostDetailByDetailType(Integer detailType, Long feeCategoryId, Long productId, Date startDate, Date endDate, SysUser sysUser) {
        if (startDate.getTime()>endDate.getTime()){
            throw new BusException("开始时间必须小于等于结束时间");
        }
        ProductCostDetailVo productCostDetailVo=new ProductCostDetailVo();
        if (detailType==0){//明细

        }else if (detailType==1){//子类型
            String mainAccountFeeCategory = siteConfigService.getConfigValueFromCache("product_feeCategory");
            List<FeeCategoryTreeMapVo> allFeeCategoryTreeMapVoList = JSONArray.parseArray(mainAccountFeeCategory, FeeCategoryTreeMapVo.class);
            List<FeeCategoryTreeMapVo> feeCategoryTreeMapVoList=businessStatisticsService.findChildListByParentId(allFeeCategoryTreeMapVoList,feeCategoryId);
            List<ProductCostByCategoryVo> productCostByCategoryVoList=this.findProductCategoryCostByProductId(feeCategoryTreeMapVoList,productId,startDate,endDate,sysUser);
            productCostDetailVo.setProductCostByCategoryVoList(productCostByCategoryVoList);
        }else if (detailType==2){//课酬
            List<TeacherClassCostVo> teacherClassCostVoList=this.productClassRemunerationDetail(productId,feeCategoryId,startDate,endDate,sysUser);
            productCostDetailVo.setTeacherClassCostVoList(teacherClassCostVoList);
        }

        return productCostDetailVo;
    }

    @Override
    public ProductCostDetailVo findProductCostDetail(Integer detailType, Long feeCategoryId, Long productId, Date startDate, Date endDate, SysUser sysUser,int pageNo,int pageSize) {
        if (startDate.getTime()>endDate.getTime()){
            throw new BusException("开始时间必须小于等于结束时间");
        }
        ProductCostDetailVo productCostDetailVo=new ProductCostDetailVo();
        if (detailType==0){//明细

        }else if (detailType==1){//子类型
            String mainAccountFeeCategory = siteConfigService.getConfigValueFromCache("product_feeCategory");
            List<FeeCategoryTreeMapVo> allFeeCategoryTreeMapVoList = JSONArray.parseArray(mainAccountFeeCategory, FeeCategoryTreeMapVo.class);
            List<FeeCategoryTreeMapVo> feeCategoryTreeMapVoList=businessStatisticsService.findChildListByParentId(allFeeCategoryTreeMapVoList,feeCategoryId);
            List<ProductCostByCategoryVo> productCostByCategoryVoList=this.findProductCategoryCostByProductId(feeCategoryTreeMapVoList,productId,startDate,endDate,sysUser);
            productCostDetailVo.setProductCostByCategoryVoList(productCostByCategoryVoList);
        }else if (detailType==2){//课酬
            Page<TeacherClassCostVo> teacherClassCostVoPage=this.productClassRemunerationPage(productId,feeCategoryId,startDate,endDate,sysUser,pageNo,pageSize);
            productCostDetailVo.setTeacherClassCostVoPage(teacherClassCostVoPage);
        }

        return productCostDetailVo;
    }

    @Override
    public BigDecimal calLeaveOfClassLecture(List<ClassLecture> classLectureList){
        BigDecimal lectureAmount=BigDecimal.ZERO;
        if (classLectureList==null || classLectureList.size()<=0){
            return lectureAmount;
        }
        List<Long> classIds=BeanUtils.toList(classLectureList,"classId");
        List<CourseClass> courseClassList=courseClassService.findByIds(classIds,"classId","roomId");
        Set<Long> roomIdSet=new HashSet<Long>();
        for (CourseClass courseClass:courseClassList){
            roomIdSet.add(courseClass.getRoomId());
        }
        SimpleDateFormat simpleDateFormat=new SimpleDateFormat("yyyy");
        Set<String> classDateSet=new HashSet<String>();
        for (ClassLecture classLecture:classLectureList){
            classDateSet.add(simpleDateFormat.format(classLecture.getClassDate()));
        }
        List<RoomPrice> roomPriceList=roomPriceService.findByYearsAndRoomIds(classDateSet,roomIdSet);
        Map<Long,CourseClass> courseClassMap=BeanUtils.toMap(courseClassList,"classId");
        for (ClassLecture classLecture:classLectureList){
            if (courseClassMap.containsKey(classLecture.getClassId())){
                String year=simpleDateFormat.format(classLecture.getClassDate());
                Long roomId=courseClassMap.get(classLecture.getClassId()).getRoomId();
                for (RoomPrice roomPrice:roomPriceList){
                    if (roomPrice.getYear().equals(year) && roomPrice.getRoomId().equals(roomId)){
                        Long classTime=classLecture.getClassDate().getTime();
                        int weekNum= TimeUtils.getWeekOfDate(classLecture.getClassDate());
                        if (classTime>=roomPrice.getSummerStartDate().getTime() && classTime<=roomPrice.getSummerEndDate().getTime()){//暑假
                            lectureAmount=lectureAmount.add(roomPrice.getSummerCost().multiply(new BigDecimal(2)));
                            break;
                        }else if (classTime>=roomPrice.getWinterStartDate().getTime() && classTime<=roomPrice.getWinterEndDate().getTime()){//寒假
                            lectureAmount=lectureAmount.add(roomPrice.getWinterCost().multiply(new BigDecimal(2)));
                            break;
                        }else if (weekNum==0 || weekNum==6){//周末
                            lectureAmount=lectureAmount.add(roomPrice.getWeekendCost().multiply(new BigDecimal(2)));
                            break;
                        }else {
                            lectureAmount=lectureAmount.add(roomPrice.getWorkingCost().multiply(new BigDecimal(2)));
                            break;
                        }
                    }
                }

            }
        }
        return lectureAmount;
    }


}